package framework.runtime;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.NoSuchMessageException;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Locale;
import java.util.Map;

@Component
@Slf4j
public class SystemContext implements ApplicationContextAware {

    /**
     * 上下文对象实例
     */
    private static ApplicationContext applicationContext;

    /**
     * 是否已初始完成
     */
    @Getter
    private static Boolean isInitialized = false;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SystemContext.applicationContext = applicationContext;
        this.printMessage(applicationContext);
        isInitialized = true;
    }

    /**
     * 初始化
     */
    protected void printMessage(ApplicationContext applicationContext) {
        log.info("Default locale: " + Locale.getDefault());
        log.info("Default message: " +
                applicationContext.getMessage("language", null, "No set", Locale.getDefault()));
    }

    /**
     * 获取Spring上下文
     *
     * @return
     */
    public static ApplicationContext getContext() {
        return applicationContext;
    }

    /**
     * 通过name获取Bean
     *
     * @param name
     * @return
     */
    public static Object getBean(String name) {
        return applicationContext.getBean(name);
    }

    /**
     * 通过class获取Bean
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }

    /**
     * 通过class获取一组Bean
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> Collection<T> getBeans(Class<T> clazz) {
        Map<String, T> beansOfType = applicationContext.getBeansOfType(clazz);
        return beansOfType.values();
    }

    /**
     * 通过class获取一组Bean
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> Map<String, T> getBeansMap(Class<T> clazz) {
        return applicationContext.getBeansOfType(clazz);
    }

    /**
     * 注册一个bean
     *
     * @param beanName
     * @param clazz
     * @return
     */
    public static void registerBean(String beanName, Class<?> clazz) {
        AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();
        Object bean = beanFactory.createBean(clazz);
        beanFactory.initializeBean(bean, beanName);
    }

    /**
     * 注册一个bean
     *
     * @param clazz
     * @return
     */
    public static void registerBean(Class<?> clazz) {
        applicationContext.getAutowireCapableBeanFactory().createBean(clazz);
    }

    /**
     * 通过name,以及Clazz返回指定的Bean
     *
     * @param name
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return applicationContext.getBean(name, clazz);
    }

    /**
     * 获取一个语言文本
     *
     * @param code
     * @param args
     * @param defaultMessage
     * @param locale
     * @return
     */
    public static String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale) {
        String message = applicationContext.getMessage(code, args, defaultMessage, locale);
        return message;
    }

    /**
     * 获取一个语言文本
     *
     * @param code
     * @param args
     * @param locale
     * @return
     * @throws NoSuchMessageException
     */
    public static String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException {
        String message = applicationContext.getMessage(code, args, locale);
        return message;
    }

    /**
     * 以当前主机所在区域语言获取一个语言文本
     *
     * @param code
     * @param args
     * @return
     * @throws NoSuchMessageException
     */
    public static String getMessage(String code, Object... args) throws NoSuchMessageException {
        String message = applicationContext.getMessage(code, args, Locale.getDefault());
        return message;
    }

    /**
     * 以当前主机所在区域语言获取一个语言文本
     *
     * @param code
     * @param args
     * @param defaultMessage
     * @return
     * @throws NoSuchMessageException
     */
    public static String getMessageDefault(String code, String defaultMessage, Object... args) throws NoSuchMessageException {
        String message = applicationContext.getMessage(code, args, defaultMessage, Locale.getDefault());
        return message;
    }

}
